/*
  InheritedWidget
  提供了一种数据在widget树中从上到下传递、共享的方式，
  在他下面的组件都可以通过静态方法获取InheritedWidget对象

  局部刷新：
  1.自行封装StatefulWidget,调用其setState方法，不推荐
  2.使用ValueListenableBuilder，本质上仍然是StatefulWidget的封装

  一般做法是根布局是有状态的，子控件都是无状态
 */

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(
  home: HomePage(),
));

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('State'),),
      body: BodyWidget(),
    );
  }
}

class BodyWidget extends StatefulWidget {
  @override
  _BodyWidgetWidgetState createState() => _BodyWidgetWidgetState();
}

class _BodyWidgetWidgetState extends State<BodyWidget> {

  // 创建通知者
  ValueNotifier<int> _notifier = ValueNotifier(0);

  @override
  Widget build(BuildContext context) {
    debugPrint('BodyWidget build');
    return CountWidget(
      _notifier.value,
      // 用ValueListenableBuilder封装
      child: ValueListenableBuilder<int>(
        valueListenable: _notifier,
        builder: (BuildContext ctx, int value, Widget? child){
          return Column(
            children: [
              _TestWidget(),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  ElevatedButton(onPressed: (){
                    setState(() {
                      _notifier.value--;
                    });
                  }, child: Icon(Icons.remove)),
                  _TestWidget(),
                  ElevatedButton(onPressed: (){
                    setState(() {
                      _notifier.value++;
                    });
                  }, child: Icon(Icons.add)),
                ],
              )
            ],
          );
        }
      ),
    );
  }
}

class _TestWidget extends StatefulWidget {
  @override
  __TestWidgetState createState() => new __TestWidgetState();
}

class __TestWidgetState extends State<_TestWidget> {
  @override
  Widget build(BuildContext context) {
    // 使用InheritedWidget中的共享数据
    // 当父控件重新绘制的时候会调用本类中的build方法
    print('TestWidgetState build');
    CountWidget countWidget = CountWidget.of(context);
    return Text('${countWidget.count}');
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。
    // 如果build中没有依赖InheritedWidget，则此回调不会被调用。
    // 一般来说，子widget很少会重写此方法，因为在依赖改变后framework也都会调用build()方法。
    // 但是，如果你需要在依赖改变后执行一些昂贵的操作，比如网络请求，这时最好的方式就是在此方法中执行，这样可以避免每次build()都执行这些昂贵操作。
    print("TestWidgetState Dependencies change");
  }
}

// 自定义类继承InheritedWidget
// 属于无状态组件
class CountWidget extends InheritedWidget {

  final int count;

  CountWidget(this.count, {required Widget child}):super(child: child);

  static CountWidget of(BuildContext context) {
    // 会调用被本控件包裹的控件的didChangeDependencies方法
    return context.dependOnInheritedWidgetOfExactType<CountWidget>()!;

    // 不会回调didChangeDependencies
    //  return context.getElementForInheritedWidgetOfExactType<CountWidget>().widget;
  
  }

  // 实现该方法
  @override
  bool updateShouldNotify(CountWidget oldWidget) {
    return count != oldWidget.count;
  }
}